import { auth, Box3Post } from "@ap/util/request";
import { BodyInit } from "@ap/types/request";
import { concatString, tasks } from "@ap/util/data";
import { FolderReader } from "./translate";
import { apiAndPCType, apiType } from "@ap/util/request";

import FormData from "form-data";
import axios from "axios";

import { PackageConfig } from "src/types/config";
type ClientConfig = {
  token: string;
  mapId: string;
  folderReader: FolderReader;
  ua?: string;
};

class Client {
  static Endpoints = {
    update: "open/script/save-or-update",
  };
  static FileMetas = {
    0: {
      file: "_server_bundle.js",
    },
    1: {
      file: "_client_bundle.js",
    },
  };

  constructor(protected config: ClientConfig) {}

  async updateFile(
    type: keyof typeof Client.FileMetas,
    content: string | Buffer,
    arenaProServerOutputName?: string,
    arenaProClientOutputName?: string,
    typePackage?: void | "server" | "client",
  ): Promise<true | Error> {
    if (
      (typePackage === "server" && type !== 0) ||
      (typePackage === "client" && type !== 1)
    ) {
      return true;
    }
    const fileMeta = Client.FileMetas[type];
    if (arenaProServerOutputName && arenaProClientOutputName) {
      if (type === 0) {
        fileMeta.file = arenaProServerOutputName;
      } else if (type === 1) {
        fileMeta.file = arenaProClientOutputName;
      }
    }

    const fileContent = Buffer.isBuffer(content)
      ? content
      : Buffer.from(content, "utf-8");

    const formData = new FormData();
    formData.append("mapId", this.config.mapId.toString());
    formData.append("name", fileMeta.file);
    formData.append("type", type.toString());
    formData.append("file", fileContent, {
      filename: fileMeta.file,
      contentType: "application/javascript",
    });

    return new Promise<true | Error>((resolve, reject) => {
      axios({
        method: "post",
        url: apiAndPCType[apiType].api + Client.Endpoints.update,
        headers: {
          Authorization: auth,
          "X-Dao-Ua":
            this.config.ua ||
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
        },
        data: formData,
        maxBodyLength: Infinity,
      })
        .then((res) => {
          const data = res.data;
          if (res.status !== 200 || data.code !== 200) {
            const e = new Error(
              "上传js文件失败，错误码：" + data.code + "\n原因：" + data.msg,
            );
            console.log("[ERROR]", e);
            resolve(e);
          }
          resolve(true);
        })
        .catch((error) => {
          console.log(error);
          resolve(error instanceof Error ? error : new Error(error));
        });
    });
  }
  async updateAllFiles(
    typePackage: void | "server" | "client" | undefined,
    files: [string | Buffer, string | Buffer],
    server: string | undefined,
    client: string | undefined,
  ): Promise<void> {
    const res = await tasks(
      files.map(
        (content, type) => () =>
          this.updateFile(type as 0 | 1, content, server, client, typePackage),
      ),
    );
    const rejected = res.filter((v) => v instanceof Error);
    if (rejected.length) {
      throw new Error(rejected[0].message);
    }
  }

  get token() {
    return auth;
  }
}

export { Client };
